<?php
	//Doctor, subclass of User
	class Doctor extends User{
		private $doctor_regno;
		private $doctor_speciality;
		private $doctor_verified;
	
		//Note: Constructor does not set ID however insert() and Doctor::createUser() sets ID
		//      Use Doctor::createUser() for manipulation of Doctor
		
		//Constructor for Doctor
		//
		//Param: username, password, email, firstname, lastname, 
		//		 gender, address, contact, date of birth, role, time
		//		 doctor regno, doctor speciality, doctor verified = false
		function __construct($user_username, $user_password, $user_email, 
								$user_firstname, $user_lastname, $user_gender, 
								$user_address, $user_contact, 
								$user_dob, $user_role, $user_time,
								$doctor_regno, $doctor_speciality, 
								$doctor_verified = false) {

			parent::__construct($user_username, $user_password, $user_email, 
								$user_firstname, $user_lastname, $user_gender, 
								$user_address, $user_contact, 
								$user_dob, $user_role, $user_time);
			$this->setRegno($doctor_regno);
			$this->setSpeciality($doctor_speciality);
			$this->setVerified($doctor_verified);
		}
		
		//Setter for Regno (registration no)
		function setRegno($val) {
			$this->doctor_regno = $val;
		}
		//Getter for Regno (registration no)
		function getRegno() {
			return $this->doctor_regno;
		}

		//Setter for Speciality
		function setSpeciality($val) {
			$this->doctor_speciality = $val;
		}
		//Getter for Speciality
		function getSpeciality() {
			return $this->doctor_speciality;
		}
		
		//Setter for Verified
		function setVerified($val) {
			$this->doctor_verified = $val;
		}
		//Getter for Verified
		function getVerified() {
			return $this->doctor_verified;
		}

		//Insert new Doctor info into database
		//
		//Return: User ID or O		
		function insert() {
			//Calls User::insert()
			$user_id = parent::insert();
			$db = Database::get();
			$query = "INSERT INTO " . DOCTOR_TABLE . " 
				(user_id, doctor_regno, doctor_speciality, doctor_verified)
				VALUES(?, ?, ?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$doctor_regno = $this->getRegno();
				$doctor_speciality = $this->getSpeciality();
				$doctor_verified = $this->getVerified();
				
				$stmt->bind_param("dssi", $user_id, $doctor_regno, $doctor_speciality, 
									$doctor_verified);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$stmt->close();
			}
			return intval($user_id);
		}

		//Create Doctor object given the ID by taking information from the database
		//Information taken from the database: username, email, first name, last name,
		//	gender, address, contact, date of birth (dob), role, time, valid token,
		//	registration no, speciality, verified
		//
		//Param: user id
		//Return: Doctor object		
		static function createUser($id) {
			$db = Database::get();
			$query = "SELECT * FROM " . DOCTOR_TABLE . " INNER JOIN " . USER_TABLE . "
					  ON user.user_id = doctor.user_id
					  WHERE doctor.user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$result = $stmt->get_result();
				$doctor_row = null;
				if ($row = $result->fetch_assoc()) {
					$doctor_row = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor: ' . $db->error);
			}
			
			$user = null;
			if ($doctor_row !== null) {
				$doctor_regno = $doctor_row['doctor_regno'];
				$doctor_speciality = $doctor_row['doctor_speciality'];
				$doctor_verified = $doctor_row['doctor_verified'];
				
				$user_username = $doctor_row['user_username'];
				$user_email = $doctor_row['user_email']; 

				$user_firstname = $doctor_row['user_firstname'];
				$user_lastname = $doctor_row['user_lastname'];
				$user_gender = $doctor_row['user_gender'];
				
				//Decode start
				$user_address = base64_decode($doctor_row['user_address']);
				$user_contact = base64_decode($doctor_row['user_contact']);
				$user_dob = base64_decode($doctor_row['user_dob']);
				//Decode end
				$user_role = $doctor_row['user_role'];
				$user_time = $doctor_row['created_at'];

				$user_valid = $doctor_row['user_valid'];
				
				$user = new Doctor($user_username, null, $user_email, $user_firstname, $user_lastname, 
							$user_gender, $user_address, $user_contact, $user_dob, $user_role, $user_time,
							$doctor_regno, $doctor_speciality, $doctor_verified);
				$user->setUserID($id);
				$user->setValid($user_valid);
				}
			
			return $user;
		}

		//Attach the Doctor from the hospital given the hospital ID
		//
		//Param: hospital id
		//Return: true or false
		function attachToHospital($hospital_id) {
			$db = Database::get();
			$query = "INSERT INTO " . DOCTOR_HOSPITAL_TABLE . " 
				(user_id, hospital_id) VALUES(?, ?);";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();

				$stmt->bind_param("dd", $user_id, $hospital_id);
				$stmt->execute() or die('Invalid query for Doctor Hospital: ' . $db->error);
				$stmt->close();
				return true;
			}
			return false;
		}
		
		//Unattach the Doctor from the hospital given the hospital ID
		//
		//Param: hospital id
		//Return: true or false
		function unattachFromHospital($hospital_id) {
			$db = Database::get();
			$query = "DELETE FROM " . DOCTOR_HOSPITAL_TABLE . " 
				WHERE user_id = ? AND hospital_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$stmt->bind_param("dd", $user_id, $hospital_id);
				$stmt->execute() or die('Invalid query for Doctor Hospital: ' . $db->error);
				$stmt->close();
				return true;
			}
			return false;
		}
		
		//Get list of the hospital attached to the Doctor
		//
		//Return: List of hospital
		function getHospitalList() {
			$hospital_list = null;
			$db = Database::get();
			$query = "SELECT * FROM " . DOCTOR_HOSPITAL_TABLE . "
				INNER JOIN " . HOSPITAL_TABLE . "
				ON " . DOCTOR_HOSPITAL_TABLE . ".hospital_id = " . HOSPITAL_TABLE . ".hospital_id
				WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$user_id = $this->getUserID();
				
				$stmt->bind_param("d", $user_id);
				
				$stmt->execute() or die('Invalid query for Doctor Hospital: ' . $db->error);
				$result = $stmt->get_result();
				
				while ($row = $result->fetch_assoc()) {
					$hospital_list[] = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor Hospital: ' . $db->error);
			}
			
			return $hospital_list;
		}		
		
		//Remove request pending of the patient given the patient id
		//
		//Param: patient id
		//Return: true or false
		function removeRequestFrom($patient_id) {
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "DELETE FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$request_pending = true;
				
				$stmt->bind_param("dd", $user_id, $patient_id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			
			//No notification	
			return false;
		}
		
		//Set request pending of the given patient
		//
		//Param: patient id, value (true or false)
		//Return: true or false
		function setRequestPending($patient_id, $val) {
			$user_id = parent::getUserID();
			$db = Database::get();
			$query = "UPDATE " . DOCTOR_PATIENT_TABLE . "
				SET request_pending = ?
				WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {		
				$stmt->bind_param("ddd", $val, $user_id, $patient_id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$stmt->close();			
				return true;
			}
			return false;
		}

		//Accept patient's request given the patient id and set pending to false
		//
		//Param: patient id
		//Return: accepted (true or false)
		function acceptRequest($patient_id) {
			$accepted = $this->setRequestPending($patient_id, false);
			$request_id = Patient::findRequestID($patient_id);
			$user_id = parent::getUserID();
			//Create notification for the patient to input into database
			$notification_message = str_replace('PERSON', User::findName($user_id), REQUEST_PATIENT_MSG);
			$notification_type_id = Notification::findTypeID('request_patient');
			$notification = new Notification($patient_id, $notification_type_id, $notification_message, $user_id, $request_id, null);
			$notification->insert();
			
			return $accepted;
		}

		//Get the list of patients of the Doctor
		//
		//Return: list of patient 
		function getPatientList() {
			$user_id = parent::getUserID();
			$patient_list = null;
			$db = Database::get();
			$query = "SELECT * FROM " . DOCTOR_PATIENT_TABLE . " 
				WHERE doctor_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {			
				$stmt->bind_param("d", $user_id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$result = $stmt->get_result();
				while($row = $result->fetch_assoc()) {
					$patient_list[] = $row;
				} 
				$stmt->close();
			}
			
			return $patient_list;
		}				

		//Find if the doctor is attached to the patient given the patient id
		//
		//Param: patient id
		//Return: true or false
		function isPatient($patient_id) {
			$user_id = parent::getUserID();
			$id = 0;
			$db = Database::get();
			$query = "SELECT patient_id FROM " . DOCTOR_PATIENT_TABLE . "
					  WHERE doctor_id = ? AND patient_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("dd", $user_id, $patient_id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$stmt->bind_result($id);
				$stmt->fetch() or $id = 0;
				$stmt->close();
			} else {
				die('Invalid query for Doctor: ' . $db->error);
			}
			
			if (intval($id) !== 0) {
				return true;
			}
			return false;
		}				
		
		//Find a Doctor given the Doctor ID from the database
		//Use this when viewing as a third party. If not, please use Doctor::createUser() instead
		//
		//Param: doctor id
		//Return: doctor info (array)		
		static function findDoctor($doctor_id) {
			$doctor = null;
			$db = Database::get();
			$query = "SELECT " . DOCTOR_TABLE. ".user_id, 
					user_firstname, user_lastname, user_email, user_gender, user_contact, 
					doctor_regno, doctor_speciality 
					FROM " . DOCTOR_TABLE . "
					INNER JOIN " . USER_TABLE. " 
					ON " . USER_TABLE . ".user_id=" . DOCTOR_TABLE. ".user_id
					WHERE " . DOCTOR_TABLE. ".user_id=?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("d", $doctor_id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$result = $stmt->get_result();
				if ($row = $result->fetch_assoc()) {
					$doctor = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor: ' . $db->error);
			}
			
			//Decode
			$doctor['user_contact'] = base64_decode($doctor['user_contact']);
			
			return $doctor;
		}	
		
		//Get the list of hospital of the Doctor given the id
		//
		//Return: list of hospital of the Doctor
		static function findHospitalList($user_id) {
			$hospital_list = null;
			$db = Database::get();
			$query = "SELECT * FROM " . DOCTOR_HOSPITAL_TABLE . "
				INNER JOIN " . HOSPITAL_TABLE . "
				ON " . DOCTOR_HOSPITAL_TABLE . ".hospital_id = " . HOSPITAL_TABLE . ".hospital_id
				WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$stmt->bind_param("d", $user_id);
				
				$stmt->execute() or die('Invalid query for Doctor Hospital: ' . $db->error);
				$result = $stmt->get_result();
				
				while ($row = $result->fetch_assoc()) {
					$hospital_list[] = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor Hospital: ' . $db->error);
			}
			
			return $hospital_list;
		}		

		//Search for the list of Doctors given the criteria
		//Criteria compares to doctor speciality, first name, last name and hospital name
		//
		//Return: list of searched Doctor	
		static function searchDoctor($criteria = '') {
			$search_list = null;
			$db = Database::get();
			$query = "SELECT *, " . DOCTOR_TABLE . ".user_id FROM " . DOCTOR_TABLE . "
					INNER JOIN " . USER_TABLE. " 
					ON " . USER_TABLE . ".user_id=" . DOCTOR_TABLE. ".user_id
					LEFT JOIN " . DOCTOR_HOSPITAL_TABLE . "
					ON " . DOCTOR_HOSPITAL_TABLE . ".user_id=" . DOCTOR_TABLE. ".user_id					
					LEFT JOIN " . HOSPITAL_TABLE . "
					ON " . DOCTOR_HOSPITAL_TABLE . ".hospital_id=" . HOSPITAL_TABLE. ".hospital_id
					WHERE (doctor_speciality LIKE CONCAT('%',?,'%') 
					OR CONCAT(CONCAT(user_firstname, ' '), user_lastname) LIKE CONCAT('%',?,'%') 
					OR hospital_name LIKE CONCAT('%',?,'%')) 
					AND doctor_verified = true
					GROUP BY " . DOCTOR_TABLE . ".user_id;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->bind_param("sss", $criteria, $criteria, $criteria);
				
				$stmt->execute() or die('Invalid query for Doctor Hospital: ' . $db->error);
				$result = $stmt->get_result();
				
				while ($row = $result->fetch_assoc()) {
					$search_list[] = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor Hospital: ' . $db->error);
			}
			//Decode start
			if ($search_list !== null) {
				for ($i = 0; $i < count($search_list); $i++) {
					$search_list[$i]['user_contact'] = base64_decode($search_list[$i]['user_contact']);
					$search_list[$i]['user_address'] = base64_decode($search_list[$i]['user_address']);
					$search_list[$i]['user_dob'] = base64_decode($search_list[$i]['user_dob']);
				}
			}
			//Decode end
			
			return $search_list;
		}		

		//Get the list of patients of all Doctor
		//
		//Return: list of patients with the patient count of all Doctor
		static function getDoctorListWithCount() {
			$db = Database::get();
			$query = "SELECT *, " . DOCTOR_TABLE . ".user_id, count(" . PATIENT_TABLE . ".user_id) as patient_count FROM " . DOCTOR_TABLE . "
					 LEFT JOIN " . DOCTOR_PATIENT_TABLE . "
					 ON " . DOCTOR_TABLE . ".user_id = " . DOCTOR_PATIENT_TABLE . ".doctor_id
					 LEFT JOIN " . PATIENT_TABLE . "
				     ON " . PATIENT_TABLE . ".user_id = " . DOCTOR_PATIENT_TABLE . ".patient_id					 				 
					 INNER JOIN " . USER_TABLE . "
				     ON " . DOCTOR_TABLE . ".user_id = " . USER_TABLE . ".user_id
				   	 GROUP BY " . DOCTOR_TABLE . ".user_id;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$result = $stmt->get_result();
				$hospital_list = null;
				while ($row = $result->fetch_assoc()) {
					$hospital_list[] = $row;
				} 
				$stmt->close();
			} else {
				die('Invalid query for Doctor: ' . $db->error);
			}

			//Decode start
			if ($hospital_list !== null) {
				for ($i = 0; $i < count($hospital_list); $i++) {
					$hospital_list[$i]['user_contact'] = base64_decode($hospital_list[$i]['user_contact']);
					$hospital_list[$i]['user_address'] = base64_decode($hospital_list[$i]['user_address']);
					$hospital_list[$i]['user_dob'] = base64_decode($hospital_list[$i]['user_dob']);
				}
			}
			//Decode end
			
			return $hospital_list;
		}

		//Change the verification of the doctor given the id and value
		//
		//Param: doctor id, val (true or false)
		//Return: true or false	
		static function changeVerified($id, $val) {
			$db = Database::get();
			$query = "UPDATE " . DOCTOR_TABLE . " 
				SET doctor_verified = ? WHERE user_id = ?;";
			$stmt = $db->prepare($query);
			if ($stmt) {
				
				$stmt->bind_param("dd", $val, $id);
				$stmt->execute() or die('Invalid query for Doctor: ' . $db->error);
				$stmt->close();
				
				return true;
			}
			return false;
		}	
		
	}
?>